package services;

import java.util.Date;
import java.util.List;

import models.Resource;
import models.ResourceType;

public class ProjectService extends ResourceService {
	
	private static final String RESOURCES_DIRECTORY = "resources/projects/";
	
	private static ProjectService service;
	
	// Singleton pattern
	private ProjectService() {
	}
	
	/**
	 * The service instance.
	 * 
	 * @return The service instance
	 */
	public static ProjectService getService() {
		if (service == null) {
			service = new ProjectService();
		}
		return service;
	}
	
	/**
	 * Returns all projects.
	 * 
	 * @return A list of projects
	 */
	public List<Resource> getAllProjects() {
		return Resource.find.where().eq("type", ResourceType.Project).findList();
	}
	
	/**
	 * Returns a project with a specified project ID
	 * 
	 * @param projectId The project ID
	 * @return The project or null if the project could not be found
	 */
	public Resource getProject(long projectId) {
		return Resource.find.byId(projectId);
	}
	
	/**
	 * Returns a project with a specified project name.
	 * 
	 * @param projectName The project name
	 * @return The project of null if the project could not be found
	 */
	public Resource getProject(String projectName) {
		return Resource.find.where().eq("name", projectName).eq("type", ResourceType.Project).findUnique();
	}
	
	/**
	 * Saves a project.
	 * 
	 * @param project The project
	 * @return The project
	 */
	public Resource saveProject(Resource project) {
		Resource result = null;
		if (project.getId() <= 0) {
			result = createProject(project);
		} else {
			result = updateProject(project);
		}
		return result;
	}
	
	private Resource createProject(Resource project) {
		Date currentDate = new Date();
		project.setType(ResourceType.Project);
		project.setCreateDate(currentDate);
		project.setLastModified(currentDate);
		project.save();
		project.setResourcePath(RESOURCES_DIRECTORY + project.getId());
		project.save();
		return project;
	}
	
	private Resource updateProject(Resource project) {
		project.setLastModified(new Date());
		project.save();
		return project;
	}
	
	/**
	 * Initial Resource entity for default configuration of a project It will not create the entity in DB.
	 * 
	 * @param project
	 * @return
	 */
	public Resource initialDefaultConfiguration(Resource project) {
		Resource config = new Resource();
		config.setName("Project configuration (" + project.getName() + ")");
		config.setType(ResourceType.TestConfiguration);
		config.setCreateDate(project.getCreateDate());
		config.setLastModified(project.getCreateDate());
		return config;
	}
	
	/**
	 * Returns the default configuration of a project.
	 * 
	 * @param projectId The project ID
	 * @return The default configuration
	 */
	public Resource getDefaultConfig(long projectId) {
		Resource defaultConfig = null;
		if (projectId > 0) {
			List<Resource> childResources = getChildResources(projectId, ResourceType.TestConfiguration);
			if (!childResources.isEmpty()) {
				defaultConfig = childResources.get(0);
			}
		}
		return defaultConfig;
	}
	
	/**
	 * Sets the default configuration of a project.
	 * 
	 * @param projectId The project ID
	 * @param defaultConfigId The configuration ID
	 */
	public void setDefaultConfig(long projectId, long defaultConfigId) {
		replaceDefaultConfig(projectId, 0, defaultConfigId);
	}
	
	/**
	 * Replaces an old default configuration with a new.
	 * 
	 * @param projectId The project ID
	 * @param oldDefaultConfigId The ID of the configuration to replace
	 * @param newDefaultConfigId The ID of the configuration to replace with
	 */
	public void replaceDefaultConfig(long projectId, long oldDefaultConfigId, long newDefaultConfigId) {
		if (projectId > 0 && newDefaultConfigId > 0) {
			if (oldDefaultConfigId > 0) {
				removeHierarchy(projectId, oldDefaultConfigId);
			}
			createHierarchy(projectId, newDefaultConfigId);
		}
	}
	
}
